package rtda

import (
	"jvm/rtda/heap"
	. "jvm/typedef"
	"math"
)

// *******************************************************
type Frame struct {
	localVars LocalVars
	opStack   OPStack
	nextPC    U4
	thread    *Thread
	method    *heap.Method
}

func (self *Frame) RevertNextPC() {
	self.nextPC = self.thread.pc
}

// getter
func (self *Frame) LocalVars() LocalVars {
	return self.localVars
}
func (self *Frame) OPStack() *OPStack {
	return &self.opStack
}
func (self *Frame) NextPC() U4 {
	return self.nextPC
}
func (self *Frame) Thread() *Thread {
	return self.thread
}
func (self *Frame) Method() *heap.Method {
	return self.method
}

// setter
func (self *Frame) SetNextPC(nextPC U4) {
	self.nextPC = nextPC
}

// *******************************************************
type Slot struct {
	num U4
	ref *heap.Object
}

// *******************************************************
type LocalVars []Slot

func newLocalVars(maxLocals U2) LocalVars {
	return make(LocalVars, maxLocals)
}

// set and get
// *******************************************************
func (self LocalVars) SetInt(index U2, val I4) {
	self[index].num = U4(val)
}
func (self LocalVars) GetInt(index U2) I4 {
	return I4(self[index].num)
}

// *******************************************************
// 大端模式存储Long，Double
func (self LocalVars) SetLong(index U2, val I8) {
	u64 := U8(val)
	self[index].num = U4(u64 >> 32)
	self[index+1].num = U4(u64 & 0xffffffff)
}
func (self LocalVars) GetLong(index U2) I8 {
	high := (U8(self[index].num)) << 32
	low := (U8(self[index+1].num))
	return I8(high | low)
}

// *******************************************************
func (self LocalVars) SetFloat(index U2, val F4) {
	bits := math.Float32bits(float32(val))
	self[index].num = U4(bits)
}
func (self LocalVars) GetFloat(index U2) F4 {
	val := math.Float32frombits(uint32(self[index].num))
	return F4(val)
}

//*******************************************************

func (self LocalVars) SetDouble(index U2, val F8) {
	num := I8(math.Float64bits(float64(val)))
	self.SetLong(index, num)
}
func (self LocalVars) GetDouble(index U2) F8 {
	bits := self.GetLong(index)
	val := math.Float64frombits(uint64(bits))
	return F8(val)
}

//*******************************************************

func (self LocalVars) SetRef(index U2, ref *heap.Object) {
	self[index].ref = ref
}
func (self LocalVars) GetRef(index U2) *heap.Object {
	return self[index].ref
}

//*******************************************************

func (self LocalVars) SetSlot(index U2, slot Slot) {
	self[index] = slot
}

func (self LocalVars) GetSlot(index U2) Slot {
	return self[index]
}
